package cn.smile.commons.encrypt.service.impl;

import cn.smile.commons.encrypt.service.EncryptService;
import cn.smile.commons.exceptions.BusinessException;
import cn.smile.commons.response.MyResponseCode;
import cn.smile.config.properties.EncryptProperties;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

@Slf4j
public class AESEncryptService implements EncryptService {
    @Resource
    private EncryptProperties encryptProperties;

    @Override
    public String encrypt(String content) {
        try {
            Cipher cipher = getCipher(Cipher.ENCRYPT_MODE);
            byte[] valueByte = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(valueByte);
        } catch (Exception e) {
            log.error("AES 加密失败, e:", e);
            throw new BusinessException(MyResponseCode.DATABASE_FIELD_ENCRYPT_AES);
        }
    }

    @Override
    public String decrypt(String content) {
        try {
            byte[] originalData = Base64.getDecoder().decode(content.getBytes(StandardCharsets.UTF_8));
            Cipher cipher = getCipher(Cipher.DECRYPT_MODE);
            byte[] valueByte = cipher.doFinal(originalData);
            return new String(valueByte);
        } catch (Exception e) {
            log.error("AES 解密失败: e:", e);
            throw new BusinessException(MyResponseCode.DATABASE_FIELD_DECRYPT_AES);
        }
    }

    @NotNull
    private Cipher getCipher(int decryptMode) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
        SecretKeySpec secretKey = new SecretKeySpec(encryptProperties.getKey().getBytes(StandardCharsets.UTF_8), Constants.AES);
        byte[] enCodeFormat = secretKey.getEncoded();
        SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, Constants.AES);
        IvParameterSpec iv = new IvParameterSpec(encryptProperties.getIv().getBytes(StandardCharsets.UTF_8));
        Cipher cipher = Cipher.getInstance(Constants.AES_CBC_CIPHER);
        cipher.init(decryptMode, secretKeySpec, iv);
        return cipher;
    }
}
